﻿namespace DymanicArray
{
    /// <summary>
    /// Class for dynamic array
    /// </summary>
    public class DynArray
    {
        #region Constructors

        /// <summary>
        /// Initialize new dynamic mass
        /// </summary>
        public DynArray()
        {
            pointer = -1;
            mass = new int[100];
        }

        #endregion

        #region Properties

        /// <summary>
        /// Get amount of elements in mass
        /// </summary>
        public int Count { get { return pointer + 1; } }

        /// <summary>
        /// Index Get/Set
        /// </summary>
        /// <param name="pos">Element position</param>
        /// <returns>Element</returns>
        public int this[int pos]
        {
            get
            {
                if (pos < Count && pos >= 0)
                {
                    return mass[pos];
                }
                else
                {
                    throw new System.IndexOutOfRangeException();
                }

            }
            set
            {
                if (pos < Count && pos >= 0)
                {
                    mass[pos] = value;
                }
                else
                {
                    throw new System.IndexOutOfRangeException();
                }
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Clear mass
        /// </summary>
        public void Clear()
        {
            pointer = -1;
        }

        /// <summary>
        /// Find index of the element in mass
        /// </summary>
        /// <param name="value">Element value</param>
        /// <returns>Index [0;count-1]. -1 - if not found</returns>
        public int IndexOf(int value)
        {
            int index = -1;

            for (int i = 0; i < pointer; i++)
            {
                if (mass[i] == value)
                {
                    index = i;
                    break;
                }
            }

            return index;
        }

        /// <summary>
        /// Add element at the end
        /// </summary>
        /// <param name="value">Element value</param>
        public void Add(int value)
        {
            Add(value, Count);
        }

        /// <summary>
        /// Add element at the start
        /// </summary>
        /// <param name="value">Element value</param>
        public void AddFirst(int value)
        {
            Add(value, 0);
        }

        /// <summary>
        /// Add element at the position
        /// </summary>
        /// <param name="value">Element value</param>
        /// <param name="pos">Element position</param>
        public void Add(int value, int pos)
        {
            if (pos <= Count && pos >= 0)
            {
                ensureCapacity(1);
                System.Array.Copy(mass, pos, mass, pos + 1, Count - pos + 1);
                pointer++;
                mass[pos] = value;
            }
            else
            {
                throw new System.IndexOutOfRangeException();
            }
        }

        /// <summary>
        /// Delete element in some position
        /// </summary>
        /// <param name="pos">Element position</param>
        public void RemoveAt(int pos)
        {
            if (pos < Count && pos >= 0)
            {
                System.Array.Copy(mass, pos + 1, mass, pos, Count - pos + 1);
                pointer--;
            }
            else
            {
                throw new System.IndexOutOfRangeException();
            }
        }

        /// <summary>
        /// Delete elemnt from mass
        /// </summary>
        /// <param name="value">Element value</param>
        public void Remove(int value)
        {
            try
            {
                RemoveAt(IndexOf(value));
            }
            catch
            {
                throw new System.IndexOutOfRangeException();
            }
        }

        /// <summary>
        /// Delete last element
        /// </summary>
        public void Remove()
        {
            try
            {
                RemoveAt(pointer);
            }
            catch
            {
                throw new System.IndexOutOfRangeException();
            }
        }

        /// <summary>
        /// Initialize my mass with array
        /// </summary>
        /// <param name="x">array</param>
        public void InitWithMass(int[] x)
        {
            mass = new int[100];
            pointer = -1;
            foreach (var elem in x)
            {
                Add(elem);
            }
        }

        public bool Compare(int[] comp)
        {
            bool rez = true;

            if (this.Count != comp.Length) return false;

            for (int i = 0; i < comp.Length; i++)
            {
                if (mass[i] != comp[i])
                {
                    rez = false;
                    break;
                }
            }

            return rez;
        }

        #endregion

        #region Private Logic

        /// <summary>
        /// Ensure mass capacity 
        /// </summary>
        /// <param name="increase">Amount of element which will be added</param>
        private void ensureCapacity(int increase)
        {
            if (Count + increase >= mass.Length)
            {
                reSize();
            }
        }

        /// <summary>
        /// Resize mass
        /// </summary>
        private void reSize()
        {
            int oldCapacity = mass.Length;
            int[] copmass = new int[oldCapacity];
            mass.CopyTo(copmass, 0);
            mass = new int[2 * oldCapacity];
            copmass.CopyTo(mass, 0);
        }

        #endregion

        #region Private Fields

        /// <summary>
        /// my array
        /// </summary>
        private int[] mass;

        /// <summary>
        /// point on last element in mass
        /// </summary>
        private int pointer;

        #endregion
    }
}
